package io.kiki.sba.registry.server.metadata.remoting.meta;

import io.kiki.sba.registry.common.model.GenericResponse;
import io.kiki.sba.registry.common.model.metaserver.inter.heartbeat.HeartbeatRequest;
import io.kiki.sba.registry.common.model.metaserver.nodes.CentralControlNode;
import io.kiki.sba.registry.common.model.store.Url;
import io.kiki.sba.registry.server.metadata.MetadataLeaderService;
import io.kiki.sba.registry.server.metadata.bootstrap.config.NodeConfig;
import io.kiki.sba.registry.server.metadata.bootstrap.config.ServerConfig;
import io.kiki.sba.registry.server.shared.env.ServerEnv;
import io.kiki.sba.registry.util.ConcurrentUtils;
import io.kiki.sba.registry.util.WakeUpLoopExecuteTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;


public class MetaServerRenewService {

    protected final Logger logger = LoggerFactory.getLogger("META-RENEW");
    @Autowired
    protected LocalCentralControlExchanger localMetaExchanger;
    @Autowired
    protected ServerConfig serverConfig;
    @Autowired
    private MetadataLeaderService metadataLeaderService;
    @Autowired
    private NodeConfig nodeConfig;
    private Renewer renewer;

    public synchronized void startRenewer(int intervalMs) {

        if (renewer != null) {
            throw new IllegalStateException("has started renewer");
        }
        this.renewer = new Renewer(intervalMs);
        ConcurrentUtils.createDaemonThread("metaNode-renewer", this.renewer).start();
    }

    public void renewNode() {
        final String leaderIp = metadataLeaderService.getLeader();
        HeartbeatRequest heartbeatRequest = new HeartbeatRequest<>(createNode(), -1L, nodeConfig.getLocalDataCenter(), System.currentTimeMillis(), null, null);

        boolean success = true;
        final long startTimestamp = System.currentTimeMillis();
        try {
            GenericResponse resp = (GenericResponse) localMetaExchanger.sendRequest(serverConfig.getLocalDataCenter(), heartbeatRequest).getResult();

            if (resp == null || !resp.isSuccess()) {
                success = false;
                logger.error("[RenewNodeTask] renew meta node to metaLeader error, leader: {}, resp: {}", leaderIp, resp);
            }
        } catch (Throwable t) {
            success = false;
            logger.error("[RenewNodeTask] renew node to metaLeader error, leader: {}", leaderIp, t);
        } finally {
            logger.info("[renewMetaLeader]{},leader={},span={}", success ? 'Y' : 'N', leaderIp, System.currentTimeMillis() - startTimestamp);
        }
    }

    private CentralControlNode createNode() {
        return new CentralControlNode(new Url(ServerEnv.IP), nodeConfig.getLocalDataCenter());
    }

    private final class Renewer extends WakeUpLoopExecuteTask {
        final int intervalMs;

        Renewer(int intervalMs) {
            this.intervalMs = intervalMs;
        }

        @Override
        public void _execute_() {
            try {

                // heartbeat on leader
                renewNode();
            } catch (Throwable e) {
                logger.error("failed to renewNode", e);
            }
        }

        @Override
        public int getWaitingMillis() {
            return intervalMs;
        }
    }
}
